package com.jinsi.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jinsi.pojo.SyUser;
import com.jinsi.service.yrf.UserService;
import com.jinsi.service.yrf.iml.CustomUserDetailsService;
import com.jinsi.util.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/***
 * Spring security配置类
 * 吕昊燃
 * @Date 2022/10/12
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Autowired
    private UserService userService;

    /**
     *  密码校验
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 拿到数据库的密码进行加密
         */
        auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            /**
             * 将数据库的密码和登录输入的密码进行对比
             * @param charSequence
             * @param s
             * @return
             */
            @Override
            public boolean matches(CharSequence charSequence, String s) {

                return s.equals(charSequence.toString());
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 如果有允许匿名的url，填在下面
//                .antMatchers().permitAll()
                .anyRequest().authenticated()
                .and()
                // 设置登陆页
                .formLogin().loginPage("/login1")
                //ajax提交的路径
                .loginProcessingUrl("/login1")
                // 设置登陆成功页
                .defaultSuccessUrl("/index").permitAll()
//                 自定义登陆用户名和密码参数，默认为username和password
                .usernameParameter("username")
                .passwordParameter("password")
                //发送ajax请求成功的回调
                .successHandler(new SimpleUrlAuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException, IOException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        ServletOutputStream out = httpServletResponse.getOutputStream();
                        ObjectMapper objectMapper = new ObjectMapper();
                        String name = SecurityContextHolder.getContext().getAuthentication().getName();
                        SyUser userByNameAndPwd = userService.getUserByNameAndPwd(name);
                        httpServletRequest.getSession().setAttribute("user", userByNameAndPwd);
                        objectMapper.writeValue(out, R.ok(userByNameAndPwd));
                        out.flush();
                        out.close();
                    }
                })
                //发送ajax请求失败的回调
                .failureHandler(new SimpleUrlAuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        ServletOutputStream out = httpServletResponse.getOutputStream();
                        ObjectMapper objectMapper = new ObjectMapper();
                        objectMapper.writeValue(out, R.error());
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .logout().permitAll();

        // 关闭CSRF跨域
        http.csrf().disable()
        //允许iframe页面嵌套
        .headers().frameOptions().disable();

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 设置拦截忽略文件夹，可以对静态资源放行
        web.ignoring().antMatchers("/css/**", "/js/**","/img/**","/layui/**","/zTree_v3-master/**","/kaptcha","/yzm","/login2","/register/htl","/login/htl","/redister");
    }
}
